#include <string.h>
#include <errno.h>
#include "port_event.h"
#include "http_server.h"
#include "log.h"

int port_create_event_manager (int size)
{
	int fd;

	if ((fd = port_create ()) < 0) {
		if (http_server.log_fd != -1) {
			log_error ("port_create: %s.", strerror (errno));
		}

		return -1;
	}

	return fd;
}

int port_add_fd (int fd, int events)
{
	if (port_associate (http_server.event_manager, PORT_SOURCE_FD, (uintptr_t) fd, events, NULL) < 0) {
		if (http_server.log_fd != -1) {
			log_error ("port_associate: %s.", strerror (errno));
		}

		return -1;
	}

	return 0;
}

int port_del_fd (http_connection_t *http_connection)
{
	if (port_dissociate (http_server.event_manager, PORT_SOURCE_FD, (uintptr_t) http_connection->sd) < 0) {
		if (http_server.log_fd != -1) {
			log_error ("port_dissociate: %s.", strerror (errno));
		}

		return -1;
	}

	return 0;
}

int port_del_listener (int fd)
{
	if (port_dissociate (http_server.event_manager, PORT_SOURCE_FD, (uintptr_t) fd) < 0) {
		if (http_server.log_fd != -1) {
			log_error ("port_dissociate: %s.", strerror (errno));
		}

		return -1;
	}

	return 0;
}

int port_event_wait (int timeout)
{
	struct timespec ts;
	struct timespec *pts;
	uint_t nget;

	if (timeout < 0) {
		pts = NULL;
	} else {
		ts.tv_sec = timeout / 1000;
		ts.tv_nsec = (timeout % 1000) * 1000000;
		pts = &ts;
	}

	nget = 1;
	if (port_getn (http_server.event_manager, http_server.events, http_server.max_file_descriptors, &nget, pts) < 0) {
		return -1;
	}

	return nget;
}

int port_prepare_for_reading (http_connection_t *http_connection)
{
	if (port_associate (http_server.event_manager, PORT_SOURCE_FD, (uintptr_t) http_connection->sd, POLLIN, NULL) < 0) {
		if (http_server.log_fd != -1) {
			log_error ("port_associate: %s.", strerror (errno));
		}

		return -1;
	}

	http_connection->filter = FILTER_READ;

	return 0;
}

int port_prepare_for_writing (http_connection_t *http_connection)
{
	if (port_associate (http_server.event_manager, PORT_SOURCE_FD, (uintptr_t) http_connection->sd, POLLOUT, NULL) < 0) {
		if (http_server.log_fd != -1) {
			log_error ("port_associate: %s.", strerror (errno));
		}

		return -1;
	}

	http_connection->filter = FILTER_WRITE;

	return 0;
}

int port_remove_notifications (http_connection_t *http_connection)
{
	if (http_connection->filter < NO_FILTER) {
		if (port_dissociate (http_server.event_manager, PORT_SOURCE_FD, (uintptr_t) http_connection->sd) < 0) {
			if (http_server.log_fd != -1) {
				log_error ("port_dissociate: %s.", strerror (errno));
			}

			return -1;
		}
	}

	http_connection->filter = NO_FILTER;

	return 0;
}
